package cn.yunyichina.provider.merchant.task.execute;

import cn.yunyichina.provider.framework.data.SpringContextHandler;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.provider.merchant.dao.MerchantMessageDao;
import cn.yunyichina.provider.merchant.entity.MerchantConfig;
import cn.yunyichina.provider.merchant.entity.MerchantMessage;
import cn.yunyichina.provider.merchant.entity.MethodRouter;
import cn.yunyichina.provider.merchant.util.DataUtil;
import cn.yunyichina.utils.commons.DateUtils;
import cn.yunyichina.utils.log.Log;
import cn.yunyichina.utils.log.constant.LogScene;
import com.alibaba.fastjson.JSON;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by kevin on 2017/12/7.
 */
public class MerchantNotifyMessageExecute {

    //最大推送次数
    private final static int MAX_NOTIFY_COUNT=24;

    //推送的时间范围 -3为3天前
    private final static int BEFORE_NOTIFY_DAY=-3;

    public void start() {
        //取出所有公司配置
        Map<String, MerchantConfig> merchantConfigMap = DataUtil.getAllMerchantConfig();

        //取出所有方法路由
        Map<String, MethodRouter> methodRouterMap = DataUtil.getAllMethodRouters();

        //从数据库取出需要推送的数据
        MerchantMessage wheres = new MerchantMessage();
        wheres.setBeginCreatedTime(DateUtils.getBetweenDay(BEFORE_NOTIFY_DAY));
        wheres.setEndCreatedTime(DateUtils.dateToString(new Date()));
        wheres.setNotifyFlag((short) 0);
        MerchantMessageDao merchantMessageDao = SpringContextHandler.getBean("merchantMessageDao");
        List<MerchantMessage> merchantMessageList = merchantMessageDao.select(wheres);
        Log.i(LogScene.MERCHANT_MESSAGE_NOTIFY, "从数据库取出需要推送的消息条数为:" + merchantMessageList.size() + "条");

        //循环调用方法进行推送
        for(MerchantMessage merchantMessage:merchantMessageList){
            String notifyScene=merchantMessage.getNotifyScene();
            String method=DataUtil.getMethdFromEnum(notifyScene);
            String key=merchantMessage.getOrgCode()+"_"+method;
            String handleMessage="";
            if(!methodRouterMap.containsKey(key)){
                handleMessage="该订单消息通知场景对应方法路由在表method_router未配置[key:"+key+"]!";
                Log.i(LogScene.MERCHANT_MESSAGE_NOTIFY,merchantMessage.getOrderNo(),handleMessage);
                DataUtil.updateMerchantMessageLastNotifyTime(merchantMessage.getId(),handleMessage);
                continue;
            }

            if(!merchantConfigMap.containsKey(merchantMessage.getOrgCode())){
                handleMessage="该订单组织[orgCode:"+merchantMessage.getOrgCode()+
                        ",orgName:"+merchantMessage.getOrgName()+"]在表merchant_config没有配置!";
                Log.i(LogScene.MERCHANT_MESSAGE_NOTIFY,merchantMessage.getOrderNo(),handleMessage);
                DataUtil.updateMerchantMessageLastNotifyTime(merchantMessage.getId(),handleMessage);
                continue;
            }
            MerchantConfig merchantConfig=merchantConfigMap.get(merchantMessage.getOrgCode());

            MethodRouter methodRouter=methodRouterMap.get(key);
            Object owner=SpringContextHandler.getBean(methodRouter.getServiceImpl());
            if(owner==null){
                handleMessage="该订单消息通知场景对应的服务并未实现[serviceimpl:"+methodRouter.getServiceImpl()+"]!";
                Log.i(LogScene.MERCHANT_MESSAGE_NOTIFY,merchantMessage.getOrderNo(),handleMessage);
                DataUtil.updateMerchantMessageLastNotifyTime(merchantMessage.getId(),handleMessage);
                continue;
            }

            String methodInvoke=methodRouter.getInvokeMethod();
            Method targetMethod;
            try {
                targetMethod= owner.getClass().getDeclaredMethod(methodInvoke,MerchantConfig.class,MethodRouter.class,MerchantMessage.class);
            } catch (NoSuchMethodException e) {
                handleMessage="该订单消息通知场景对应的服务,并未实现对应的3个入参为String的方法[serviceimpl:"+methodRouter.getServiceImpl()+
                        ",method:"+methodInvoke+"]!";
                Log.e(LogScene.MERCHANT_MESSAGE_NOTIFY,merchantMessage.getOrderNo(),handleMessage);
                DataUtil.updateMerchantMessageLastNotifyTime(merchantMessage.getId(),handleMessage);
                continue;
            }

            Response response=null;
            try {
                response=(Response) targetMethod.invoke(owner,new Object[]{merchantConfig,methodRouter,merchantMessage});
                Log.i(LogScene.MERCHANT_MESSAGE_NOTIFY,merchantMessage.getOrderNo(),"推送后结果:"+ JSON.toJSONString(response));
            } catch (Exception e) {
                handleMessage="该订单消息通知场景对应的服务,调用出错[serviceimpl:"+methodRouter.getServiceImpl()+
                        ",method:"+methodInvoke+"]!";
                Log.e(LogScene.MERCHANT_MESSAGE_NOTIFY,merchantMessage.getOrderNo(),handleMessage,e);
                DataUtil.updateMerchantMessageLastNotifyTime(merchantMessage.getId(),handleMessage);
            }

            //更新推送的次数
            int notifyCount=merchantMessage.getNotifyCount()+1;
            short notifyFlag=0;
            handleMessage="";
            //如果推送的次数超过最大值，直接将该订单更新成失败
            if(notifyCount>=MAX_NOTIFY_COUNT){
                notifyFlag=2;
                handleMessage="推送已经达到最大次数";
            }

            //如果是推送成功的，则更新成成功的状态
            if(response!=null){
                if(response.isSuccess()){
                    notifyFlag=1;
                    handleMessage="推送成功";
                }else{
                    handleMessage=response.getResultMessage();
                }
            }
            DataUtil.updateMerchantMessageState(merchantMessage.getId(),notifyCount,notifyFlag,handleMessage);
            Log.i(LogScene.MERCHANT_MESSAGE_NOTIFY,merchantMessage.getOrderNo(),"该笔订单该批次处理完成!");
        }

        Log.i(LogScene.MERCHANT_MESSAGE_NOTIFY,"当批次消息推送结束");
    }
}
